package org.checkboo.hopefullyengine.loaders;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import org.checkboo.hopefullyengine.sceneelements.BaseObject;
import org.checkboo.math.Vector2f;
import org.checkboo.math.Vector3f;

public class LoaderObj {
	
	public static BaseObject loadFile(File modelFile){
		BaseObject model = new BaseObject();
		
		try {
			FileInputStream is = new FileInputStream(modelFile);
			DataInputStream dis = new DataInputStream(is);
			BufferedReader br = new BufferedReader(new InputStreamReader(dis));
		
			String[] line;
			String[] face;
			Vector3f[] vertices;
			int[] indices;
			Vector3f[] normalsTmp;
			Vector2f[] texCoordsTmp;
			Vector3f[] normals;
			Vector2f[] texCoords;
			int verticesLength = 0;
			int indicesLength = 0;
			int normalsLength = 0;
			int texCoordsLength = 0;
			
			while(br.ready()){
				line = br.readLine().split(" ");
				if(line[0].equalsIgnoreCase("v"))
					verticesLength++;
				if(line[0].equalsIgnoreCase("f"))
					indicesLength++;
				if(line[0].equalsIgnoreCase("vn"))
					normalsLength++;
				if(line[0].equalsIgnoreCase("vt"))
					texCoordsLength++;
			}
			is.close();
			
			is = new FileInputStream(modelFile);
			dis = new DataInputStream(is);
			br = new BufferedReader(new InputStreamReader(dis));
			vertices = new Vector3f[verticesLength*10];
			indices = new int[indicesLength*3*10];
			normalsTmp = new Vector3f[normalsLength];
			texCoordsTmp = new Vector2f[texCoordsLength];
			normals = new Vector3f[normalsLength*10];
			texCoords = new Vector2f[texCoordsLength*10];
			
			int i=-1,j=-1,k=-1,l=-1,vertexExtra=-1;
			
			while(br.ready()){
				line = br.readLine().split("\\s+");
				if(line[0].equalsIgnoreCase("v")){
					vertices[++i] = new Vector3f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), Float.parseFloat(line[3]));
				}
				if(line[0].equalsIgnoreCase("vn")){
					normalsTmp[++k] = new Vector3f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), Float.parseFloat(line[3]));
				}
				if(line[0].equalsIgnoreCase("vt")){
					texCoordsTmp[++l] = new Vector2f(Float.parseFloat(line[1]), Float.parseFloat(line[2]));
				}
				if(line[0].equalsIgnoreCase("f")){
					
					face = line[1].split("/");
					indices[++j] = Integer.parseInt(face[0])-1;
					if(face.length == 3){
						if(null != texCoords[indices[j]] && !texCoords[indices[j]].equals(texCoordsTmp[Integer.parseInt(face[1])-1])){
							texCoords[++vertexExtra+verticesLength] = texCoordsTmp[Integer.parseInt(face[1])-1];
							vertices[vertexExtra+verticesLength] = vertices[indices[j]];
							indices[j] = vertexExtra+verticesLength;
						}
						texCoords[indices[j]] = texCoordsTmp[Integer.parseInt(face[1])-1];
						normals[indices[j]] = normalsTmp[Integer.parseInt(face[2])-1];
					}
					else{
						normals[Integer.parseInt(face[0])-1] = normalsTmp[Integer.parseInt(face[1])-1];
					}
					
					face = line[2].split("/");
					indices[++j] = Integer.parseInt(face[0])-1;
					if(face.length == 3){
						if(null != texCoords[indices[j]] && !texCoords[indices[j]].equals(texCoordsTmp[Integer.parseInt(face[1])-1])){
							texCoords[++vertexExtra+verticesLength] = texCoordsTmp[Integer.parseInt(face[1])-1];
							vertices[vertexExtra+verticesLength] = vertices[indices[j]];
							indices[j] = vertexExtra+verticesLength;
						}
						texCoords[indices[j]] = texCoordsTmp[Integer.parseInt(face[1])-1];
						normals[indices[j]] = normalsTmp[Integer.parseInt(face[2])-1];
					}
					else{
						normals[Integer.parseInt(face[0])-1] = normalsTmp[Integer.parseInt(face[1])-1];
					}
					
					face = line[3].split("/");
					indices[++j] = Integer.parseInt(face[0])-1;
					if(face.length == 3){
						if(null != texCoords[indices[j]] && !texCoords[indices[j]].equals(texCoordsTmp[Integer.parseInt(face[1])-1])){
							texCoords[++vertexExtra+verticesLength] = texCoordsTmp[Integer.parseInt(face[1])-1];
							vertices[vertexExtra+verticesLength] = vertices[indices[j]];
							indices[j] = vertexExtra+verticesLength;
						}
						texCoords[indices[j]] = texCoordsTmp[Integer.parseInt(face[1])-1];
						normals[indices[j]] = normalsTmp[Integer.parseInt(face[2])-1];
					}
					else{
						normals[Integer.parseInt(face[0])-1] = normalsTmp[Integer.parseInt(face[1])-1];
					}
					
					if(line.length == 5){
						int index = j;
						indices[++j] = indices[index - 2];
						indices[++j] = indices[index];
						
						face = line[4].split("/");
						indices[++j] = Integer.parseInt(face[0])-1;
						if(face.length == 3){
							if(null != texCoords[indices[j]] && !texCoords[indices[j]].equals(texCoordsTmp[Integer.parseInt(face[1])-1])){
								texCoords[++vertexExtra+verticesLength] = texCoordsTmp[Integer.parseInt(face[1])-1];
								vertices[vertexExtra+verticesLength] = vertices[indices[j]];
								indices[j] = vertexExtra+verticesLength;
							}
							texCoords[indices[j]] = texCoordsTmp[Integer.parseInt(face[1])-1];
							normals[indices[j]] = normalsTmp[Integer.parseInt(face[2])-1];
						}
						else{
							normals[Integer.parseInt(face[0])-1] = normalsTmp[Integer.parseInt(face[1])-1];
						}
					}
				}
			}
			is.close();
			
			model.setVertices(vertices);
			model.setIndices(indices);
			model.setTexCoords(texCoords);
			if(normalsTmp.length > 0){
				model.setVertexNormals(normals);
			}
			else
				model.calculateVertexNormals();
			
			line = null;
			face = null;
			vertices = null;
			indices = null;
			normalsTmp = null;
			texCoordsTmp = null;
			normals = null;
			texCoords = null;
			System.gc();
			
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return model;
	}
}
